﻿package
{
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.display.GradientType;
	import flash.geom.Rectangle;
	import flash.geom.Matrix;
	import flash.events.Event;
	import flash.text.*;
	
	public class HorizontalSlider extends Sprite
	{
		private var _width:Number = 100;
		private var _height:Number = 16;
		
		private var _value:Number;
		private var _max:Number = 100;
		private var _min:Number = 0;
		private var _valueChangeOnClick:Number = 0.1;
		
		//Handle
		private var _handle:Sprite;
		private var _handleWidth:Number;
		private var _handleColor:uint = 0xeeeeee;
		private var _handleBorderColor:uint = 0xcccccc;
		private var _handleRadius:Number = 2;
		private var upHandle:Boolean = true;

		//Back
		private var _back:Sprite;
		private var _backHeight:Number;
		private var _backColor:uint = 0xcccccc;
		private var _backBorderColor:uint = 0x999999;
		private var _backRadius:Number = 2;
		
		//Left-Right Arrow
		private var _LeftArrow:Sprite;
		private var _RightArrow:Sprite;
		private var scale:Number;
		private var matrix:Matrix = new Matrix;
		private var upRight:Boolean = true;
		private var redRight:Boolean = false;
		private var upLeft:Boolean = true;
		private var redLeft:Boolean = false;
		
		//Text
		private var SliderValueTF: TextField;
		private var Pos:int;
		private var Precision:int = 5;
		private var SliderValueTFwidth:Number = 60;
		private var TFformat:TextFormat;
		private var _TextOn:Boolean = false;
		
		public function HorizontalSlider(min:Number=0, max:Number=100, value:Number=0, valueChangeOnClick:Number=0.1, TextOn:Boolean = true)
		{
			_min = min;
			_max = max;
			_value = Math.min(Math.max(value, min), max)
			_valueChangeOnClick = valueChangeOnClick;
			_TextOn = TextOn;
						
			scale = _height/0.785;
			_backHeight = _height/4;
			_handleWidth = _width/10;
			
			init();
		}
		
		private function init():void
		{
			_back = new Sprite();
			addChild(_back);
			
			_handle = new Sprite();
			addChild(_handle);
			_handle.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
						
			_LeftArrow = new Sprite();
			addChild(_LeftArrow);
			_LeftArrow.addEventListener(MouseEvent.CLICK, onL_A_M_Clk);
			_LeftArrow.addEventListener(MouseEvent.MOUSE_OVER, onL_A_M_Over);
			_LeftArrow.addEventListener(MouseEvent.MOUSE_OUT, onL_A_M_Out);
			_LeftArrow.addEventListener(MouseEvent.MOUSE_DOWN, onL_A_M_Down);
			_LeftArrow.addEventListener(MouseEvent.MOUSE_UP, onL_A_M_Up);
					
			_RightArrow = new Sprite();
			addChild(_RightArrow);
			_RightArrow.addEventListener(MouseEvent.CLICK, onR_A_M_Clk);
			_RightArrow.addEventListener(MouseEvent.MOUSE_OVER, onR_A_M_Over);
			_RightArrow.addEventListener(MouseEvent.MOUSE_OUT, onR_A_M_Out);
			_RightArrow.addEventListener(MouseEvent.MOUSE_DOWN, onR_A_M_Down);
			_RightArrow.addEventListener(MouseEvent.MOUSE_UP, onR_A_M_Up);
			
			TFformat = new TextFormat();
			TFformat.align = "right";
			TFformat.size = 1.1 * _height;
			TFformat.color = 0xFFFFFF;		//White Letters
			TFformat.font = "Helvetica"; //"Times New Roman" ;
			
			SliderValueTF = new TextField();
			if(_TextOn){addChild(SliderValueTF);}

			SliderValueTF.width = SliderValueTFwidth;
			SliderValueTF.height = 2 * _height;	
			SliderValueTF.background = true;    			// Has Background
			SliderValueTF.backgroundColor = 0x000000;		//Black Background
			SliderValueTF.border =	true;
			SliderValueTF.borderColor = 0xAAAAAA;
			SliderValueTF.border = true;
			SliderValueTF.x = _width + 5*(0.75*scale);
			SliderValueTF.y = 2.4;
						
			draw();
			updatePosition();
			updateText();
		}
		
		private function draw():void
		{
			_back.x = 0.75*scale;
			drawBack();
			drawLeftArrow();
			_RightArrow.x = _width + 0.75*scale;
			drawRightArrow();
			_handle.x = 0.75*scale;
			drawHandle();
		}
		
		private function drawBack():void
		{
			_back.graphics.clear();
			
			matrix.createGradientBox(_width, _backHeight, Math.PI/2, 0, 0);					
			_back.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0x777777], [1,1], [0,255], matrix);
			_back.graphics.lineStyle(0, 0xffffff, 0);			
			_back.graphics.drawRoundRect(0, 0, _width, _backHeight, _backRadius, _backRadius);
			_back.graphics.endFill();
			_back.y = _height/2 - _backHeight/2;
		}
			
		private function drawLeftArrow():void
		{
			_LeftArrow.graphics.clear();
			matrix.createGradientBox(0.75*scale, 0.8*scale, Math.PI/2,  0, 0);
			
			if(upLeft)
				_LeftArrow.graphics.beginGradientFill(GradientType.LINEAR, [0xffffff, 0x777777], [1,1], [0,255], matrix);
			else			
				_LeftArrow.graphics.beginGradientFill(GradientType.LINEAR, [0x777777, 0xffffff], [1,1], [0,255], matrix);
			
			
			_LeftArrow.graphics.lineStyle(0, 0xffffff, 0);
			_LeftArrow.graphics.moveTo(0.2*scale, 0);
			_LeftArrow.graphics.lineTo(0.75*scale, 0);
			_LeftArrow.graphics.lineTo(0.75*scale, 0.8*scale);
			_LeftArrow.graphics.lineTo(0.2*scale, 0.8*scale);
			_LeftArrow.graphics.curveTo(0, 0.8*scale, 0, + 0.6*scale);
			_LeftArrow.graphics.lineTo(0, 0.2*scale);
			_LeftArrow.graphics.curveTo(0, 0, 0.2*scale, 0);
			
			_LeftArrow.graphics.endFill();
			           
			matrix.createGradientBox(0.45*scale, 0.5*scale, Math.PI/2, 0.3*scale, 0.15*scale);
									
			if(redLeft)			
			_LeftArrow.graphics.beginGradientFill(GradientType.LINEAR, [0xee0000, 0x770000], 
			[1,1], [0,255], matrix);
			else
			_LeftArrow.graphics.beginGradientFill(GradientType.LINEAR, [0xdddddd, 0x000000], 
			[1,1], [0,255], matrix);
			
			_LeftArrow.graphics.lineStyle(0, 0x000000, 1);
			_LeftArrow.graphics.moveTo(0.55*scale, 0.6*scale);
			_LeftArrow.graphics.lineTo(0.55*scale, 0.2*scale);
			_LeftArrow.graphics.lineTo(0.35*scale, 0.4*scale);
			_LeftArrow.graphics.lineStyle(0, 0xffffff, 1);
			_LeftArrow.graphics.lineTo(0.55*scale, 0.6*scale);
			
			_LeftArrow.graphics.lineStyle(0, 0x000000, 1);
			_LeftArrow.graphics.moveTo(0.35*scale, 0.6*scale);
			_LeftArrow.graphics.lineTo(0.35*scale, 0.2*scale);
			_LeftArrow.graphics.lineTo(0.15*scale, 0.4*scale);
			_LeftArrow.graphics.lineStyle(0, 0xffffff, 1);
			_LeftArrow.graphics.lineTo(0.35*scale, 0.6*scale);
			
			_LeftArrow.graphics.endFill();
			_LeftArrow.x = -1;
			
			
		}
		
		private function drawRightArrow():void
		{
			_RightArrow.graphics.clear();
			matrix.createGradientBox(0.75*scale, 0.8*scale, Math.PI/2,  0, 0);
			if(upRight)			
				_RightArrow.graphics.beginGradientFill(GradientType.LINEAR, [0xffffff, 0x777777], [1,1], [0,255], matrix);
			else
				_RightArrow.graphics.beginGradientFill(GradientType.LINEAR, [0x777777, 0xffffff], [1,1], [0,255], matrix);
						
			_RightArrow.graphics.lineStyle(0, 0xffffff, 0);			
			_RightArrow.graphics.moveTo(0, 0);
			_RightArrow.graphics.lineTo(0.55*scale, 0);
			_RightArrow.graphics.curveTo(0.75*scale, 0, 0.75*scale, 0.2*scale);
			_RightArrow.graphics.lineTo(0.75*scale, 0.6*scale);
			_RightArrow.graphics.curveTo(0.75*scale, 0.8*scale, 0.55*scale, 0.8*scale);
			_RightArrow.graphics.lineTo(0, 0.8*scale);
			_RightArrow.graphics.lineTo(0, 0);
			
			_RightArrow.graphics.endFill();
						
            matrix.createGradientBox(0.45*scale, 0.5*scale, Math.PI/2, 0.3*scale, 0.15*scale);
									
			if(redRight)
				_RightArrow.graphics.beginGradientFill(GradientType.LINEAR, [0xee0000, 0x770000], 
			[1,1], [0,255], matrix);
			else
				_RightArrow.graphics.beginGradientFill(GradientType.LINEAR, [0xdddddd, 0x000000], 
			[1,1], [0,255], matrix);
			
			_RightArrow.graphics.lineStyle(0, 0x000000, 1);
			_RightArrow.graphics.moveTo(0.15*scale, 0.6*scale);
			_RightArrow.graphics.lineTo(0.15*scale, 0.2*scale);
			_RightArrow.graphics.lineTo(0.35*scale, 0.4*scale);
			_RightArrow.graphics.lineStyle(0, 0xffffff, 1);
			_RightArrow.graphics.lineTo(0.15*scale, 0.6*scale);
			
			_RightArrow.graphics.lineStyle(0, 0x000000, 1);
			_RightArrow.graphics.moveTo(0.35*scale, 0.6*scale);
			_RightArrow.graphics.lineTo(0.35*scale, 0.2*scale);
			_RightArrow.graphics.lineTo(0.55*scale, 0.4*scale);
			_RightArrow.graphics.lineStyle(0, 0xffffff, 1);
			_RightArrow.graphics.lineTo(0.35*scale, 0.6*scale);
			
			_RightArrow.graphics.endFill();
			
		}
		
		private function drawHandle():void
		{
			_handle.graphics.clear();
			matrix.createGradientBox(_handleWidth, _height, Math.PI/2,  0, 0);
			
			if(upHandle)			
			_handle.graphics.beginGradientFill(GradientType.LINEAR, [0xffffff, 0x777777], [1,1], [0,255], matrix);
			else
			_handle.graphics.beginGradientFill(GradientType.LINEAR, [0x777777, 0xffffff], [1,1], [0,255], matrix);
						
			_handle.graphics.lineStyle(1, 0x333333, .8);	
			_handle.graphics.drawRoundRect(0, 0, _handleWidth, _height, _handleRadius, _handleRadius);
			_handle.graphics.endFill();
		}
	
	    private function updateText():void
		{
			SliderValueTF.text = _value.toPrecision(Precision);
			Pos = SliderValueTF.text.indexOf(".");
			SliderValueTF.text = SliderValueTF.text.substring(0,Pos+3);
			SliderValueTF.setTextFormat(TFformat);
		}
			
		private function updatePosition():void
		{
			var handleRange:Number = _width - _handleWidth;
			var valueRange:Number = _max - _min;
			_handle.x = 0.75*scale + ((_value - _min) / valueRange) * handleRange;
		}
		
		private function updateValue():void
		{
			var handleRange:Number = _width - _handleWidth;
			var valueRange:Number = _max - _min;
			_value = (_handle.x - 0.75*scale) / handleRange * valueRange + _min; 
			dispatchEvent(new Event(Event.CHANGE));
		}	
		
		//Drag Handle
		private function onMouseDown(event:MouseEvent):void
		{
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);	
			upHandle = false;
			drawHandle();
			_handle.startDrag(false, new Rectangle(0.75*scale, 0, _width - _handleWidth, 0));
		}
		
		//Stop Dragin
		private function onMouseUp(event:MouseEvent):void
		{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);			
			_handle.stopDrag();
			upHandle = true;
			drawHandle();
		}
		
		//Update Value and Text Box
		private function onMouseMove(event:MouseEvent):void
		{
			updateValue();
			updateText();
		}
		
		private function onL_A_M_Clk(event:MouseEvent):void
		{				
			_value = Math.max(_value - _valueChangeOnClick, _min);
			updatePosition();	
			updateText();		
		}
		
		private function onL_A_M_Over(event:MouseEvent):void
		{				
			upLeft = true;
			redLeft = true;
			drawLeftArrow();
		}
			
		private function onL_A_M_Out(event:MouseEvent):void
		{
			upLeft = true;
			redLeft = false;
			drawLeftArrow();
		}
		
		private function onL_A_M_Down(event:MouseEvent):void
		{
			upLeft = false;
			redLeft = true;
			drawLeftArrow();	
		}
		
		private function onL_A_M_Up(event:MouseEvent):void
		{
			upLeft = true;
			redLeft = true;
			drawLeftArrow();
		}
		
		//---------------------------------------
		
		private function onR_A_M_Clk(event:MouseEvent):void
		{				
			_value = Math.min(_value + _valueChangeOnClick, _max);
			updatePosition();	
			updateText();		
		}
		
		private function onR_A_M_Over(event:MouseEvent):void
		{				
			upRight = true;
			redRight = true;
			drawRightArrow();
		}
			
		private function onR_A_M_Out(event:MouseEvent):void
		{
			upRight = true;
			redRight = false;
			drawRightArrow();
		}
		
		private function onR_A_M_Down(event:MouseEvent):void
		{
			upRight = false;
			redRight = true;
			drawRightArrow();
		}
		
		private function onR_A_M_Up(event:MouseEvent):void
		{
			upRight = true;
			redRight = true;
			drawRightArrow();
		}
		
		//----------------------------
		
		public function invalidate():void
		{
			draw();
		}
		
		public function move(x:Number, y:Number):void
		{
			this.x = x;
			this.y = y;
		}
		
		public function setSize(w:Number, h:Number):void
		{
			_width = w;
			_height = h;
			draw();
		}
		
				
		public function set backBorderColor(n:uint):void
		{
			_backBorderColor = n;
			draw();
		}
		public function get backBorderColor():uint
		{
			return _backBorderColor;
		}
		
		public function set backColor(n:uint):void
		{
			_backColor = n;
			draw();
		}
		public function get backColor():uint
		{
			return _backColor;
		}
		
		public function set backRadius(n:Number):void
		{
			_backRadius = n;
		}
		public function get backRadius():Number
		{
			return _backRadius;
		}
		
		
		public function set handleBorderColor(n:uint):void
		{
			_handleBorderColor = n;
			draw();
		}
		public function get handleBorderColor():uint
		{
			return _handleBorderColor;
		}
		
		public function set handleColor(n:uint):void
		{
			_handleColor = n;
			draw();
		}
		public function get handleColor():uint
		{
			return _handleColor;
		}
		
		public function set handleRadius(n:Number):void
		{
			_handleRadius = n;
			draw();
		}
		public function get handleRadius():Number
		{
			return _handleRadius;
		}
		
		
		override public function set height(n:Number):void
		{
			_height = n;
			scale = _height/0.785;
			draw();
		}
		override public function get height():Number
		{
			return _height;
		}
		
		public function set max(n:Number):void
		{
			_max = n;
			updatePosition();
		}
		public function get max():Number
		{
			return _max;
		}
		
		public function set min(n:Number):void
		{
			_min = n;
			updatePosition();
		}
		public function get min():Number
		{
			return _min;
		}
		
		public function set value(n:Number):void
		{
			_value = n;
			_value = Math.min(_max, Math.max(_value, _min));
			updatePosition();
		}
		public function get value():Number
		{
			return _value;
		}
		
		override public function set width(n:Number):void
		{
			_width = n;
			draw();
		}
		override public function get width():Number
		{
			return _width;
		}
	}
}